#include "land.h"
#include "ui_land.h"

Land::Land(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Land)
{
    ui->setupUi(this);
    initialize();
    this->setLayout(gridLayout);
    this->resize(600, 400);
}

Land::~Land()
{
    delete ui;
}

// 初始化
void Land::initialize()
{
    gridLayout = new QGridLayout(this);
    initLand();
    initLandMines();
    scanLandMines();
}

// 初始化区块
void Land::initLand()
{
    for (int i = 0; i < row_num * column_num; ++i) {
        Pos *pos = indexToPos(i);
        LandBlock *block = new LandBlock(pos, this);
        connect(block, &LandBlock::isSearchChanged, this, &Land::autoDetect);
        gridLayout->addWidget(block, pos->getRow(), pos->getColumn());
        blocks.append(block);
    }
}

/**
 * @brief Land::initLandMines 初始化地雷位置，并布置地雷
 */
void Land::initLandMines()
{
    LandBlock *block;
    int count = 0;

    for (int i = 0; i < landMineMax; ++i) {
        // 随机生成地雷位置，值域[0, row_num * column_num)
        int tmp = QRandomGenerator::global()->bounded(row_num * column_num);
        int j;

        // 检查生成是否重复
        for (j = 0; j < i; ++j) {
            // 如果重复了，回退并重新生成
            if (tmp == landMinesMap[i]) {
                --i;
                break;
            }
        }
        if (i == j) landMinesMap[i] = tmp; // 没重复就存储地雷位置
    }

    // 布置地雷
    for (int i = 0; i < landMineMax; ++i) {
        blocks[landMinesMap[i]]->setHasLandMine(true);
    }
}

QList<LandBlock *> Land::findNearbyBlocks(Pos &pos)
{
    QList<LandBlock *> nearbyBlocks;
    int row = pos.getRow();
    int column = pos.getColumn();
    for (int j = -1; j < 2; ++j) {
        for (int k = -1; k < 2; ++k) {
            int tmpRow = row + j;
            int tmpColumn = column + k;
            if (tmpRow < 0 || tmpRow >= row_num ||
                    tmpColumn < 0 || tmpColumn >= column_num ||
                    (j == 0 && k == 0)) continue;
            else {
                nearbyBlocks.append(blocks.at(posToIndex(tmpRow, tmpColumn)));
            }
        }
    }
    return nearbyBlocks;
}

QList<LandBlock *> Land::findNearbyBlocks(LandBlock *block)
{
    QList<LandBlock *> empty;
    if (block == nullptr) return empty;
    return findNearbyBlocks(*(block->getBlockPos()));
}

int Land::scan(int idx)
{
    return scan(*(indexToPos(idx)));
}

int Land::scan(Pos &pos)
{
    QList<LandBlock *> nrBlocks = findNearbyBlocks(pos);
    int count = 0;
    for (int i = 0; i < nrBlocks.size(); ++i) {
        if (nrBlocks[i]->getHasLandMine()) {
            count++;
        }
    }
    return count;
}

// 扫描地雷
void Land::scanLandMines()
{
    int count;
    int row, column;
    Pos *pos;
    for (int i = 0; i < row_num * column_num; ++i) {
        blocks[i]->getContent()->setLandMinesCount(scan(i));
    }
}

Pos *Land::indexToPos(int idx)
{
    return new Pos(idx / column_num, idx % row_num);
}

int Land::posToIndex(int row, int column)
{
    return row * column_num + column;
}

int Land::posToIndex(Pos *pos)
{
    return pos->getRow() * column_num + pos->getColumn();
}

void Land::autoDetect()
{
    LandBlock *block = (LandBlock *) sender();
    QList<LandBlock *> nrBlocks = findNearbyBlocks(block);
    for (int i = 0; i < nrBlocks.length(); ++i) {
        if (nrBlocks[i]->getHasLandMine()) return;
    }
    for (int i = 0; i < nrBlocks.length(); ++i) {
        if (!nrBlocks[i]->getHasLandMine()) {
            if (!nrBlocks[i]->getIsSearch()) {
                nrBlocks[i]->setIsSearch(true);
            }
        }
    }
}
